package com.czl.myRabbitMq.mqServer.core;

import com.czl.myRabbitMq.commom.exception.mqException;

/**
 * 这个类是用来描述转发规则的类
 */
public class Router {
    //检查绑定中的key
    //routineKey 是由
    // 1. 大小写字母 数字
    // 2. 特殊符号'_' 和 '.'
    // 3. 使用'.'来作为每个部分的分割符
    // 4. 同时可以使用 '*' 和 '#' 号作为每个部分的占位符
    // '*' 号可以匹配任意一个区域 '#'号可以匹配0个多个区域
    public boolean checkBindingKey(String bindingKey){
        if(bindingKey.length() == 0){
            return true;
        }
        for(int i = 0; i < bindingKey.length(); i++){
            char key = bindingKey.charAt(i);
            //判断是不是大写字母
            if(key >= 'A' && key <= 'Z') {
                continue;
            }
            //判断小写字母
            if(key >= 'a' && key <= 'z'){
                continue;
            }
            //判断数字
            if (key >= '0' && key <= '9'){
                continue;
            }
            //判断特殊字符
            if (key == '_' || key == '.' || key == '*' || key == '#'){
                continue;
            }
            //要是都不满足则直接返回了
            return false;
        }
        //这里还需要判断 '*' 和 '#' 是不是单独在一个区域中的
        String[] words = bindingKey.split("\\.");
        for(String word : words){
            if(word.length() > 1 && (word.contains("*") || word.contains("#"))){
                return false;
            }
        }

        for(int i = 0; i < words.length - 1; i++){
            if(words[i].equals("#") && words[i + 1].equals("#")){
                return false;
            }
            if(words[i].equals("#") && words[i + 1].equals("*")){
                return false;
            }
            if(words[i].equals("*") && words[i + 1].equals("#")){
                return false;
            }
        }
        return true;
    }
    //检查消息中的routineKey
    //routineKey 是由
    // 1. 大小写字母 数字
    // 2. 特殊符号'_' 和 '.'
    // 3. 使用'.'来作为每个部分的分割符``
    public boolean checkRoutineKey(String routineKey){
        //使用FANOUT交换机的时候 routineKey是用不上的则可以为0
        if(routineKey.length() == 0){
            return true;
        }
        for(int i = 0; i < routineKey.length(); i++){
            char key = routineKey.charAt(i);
            //判断是不是大写字母
            if(key >= 'A' && key <= 'Z') {
                continue;
            }
            //判断小写字母
            if(key >= 'a' && key <= 'z'){
                continue;
            }
            //判断数字
            if (key >= '0' && key <= '9'){
                continue;
            }
            //判断特殊字符
            if (key == '_' || key == '.'){
                continue;
            }
            //要是都不满足则直接返回了
            return false;
        }
        return true;
    }
    private boolean matchKey(String bindingKey, String routineKey) {
        String[] bindingKeyWords = bindingKey.split("\\.");
        String[] routineKeyWords = routineKey.split("\\.");
        //bindingKey是带有通配符的
        if (bindingKeyWords.length == 0 && routineKeyWords.length == 0){
            return true;
        }
        int b = 0; int r = 0;
        //bindingKey *.aaa.bbb.#.aaa
        //routineKey ccc.aaa.bbb.bbb.ccc.aaa.ccc
        while (b < bindingKeyWords.length && r < routineKeyWords.length){
            if (bindingKeyWords[b].equals("*")){//当通配符是*号
                //指针直接+1
                b++;r++;
            } else if (bindingKeyWords[b].equals("#")) {
                //要是bindingKey最后一个符号是#号则直接匹配成功
                if (b == bindingKeyWords.length -1){
                    return true;
                }
                //拿到#号后面一个字符串 同时防止越界
                String end = bindingKeyWords[b + 1];
                while (true) {
                    if(r > routineKeyWords.length -1){
                        return false;
                    }
                    if (routineKeyWords[r].equals(end)) {
                        b++;
                        break;
                    }else {
                        r++;
                    }
                }
            }else {
                if(routineKeyWords[r].equals(bindingKeyWords[b])){
                    r++;b++;
                }else {
                    return false;
                }
            }
        }
        if(b == bindingKeyWords.length - 1 && r != routineKeyWords.length - 1){
            return false;
        } else if (r == routineKeyWords.length - 1 && b != bindingKeyWords.length - 1) {
            return false;
        }else {
            return true;
        }
    }

    public boolean route(ExchangeType exchangeType, Binding binding, Message message){
        //这里要是扇出交换机的话 我们直接通过 因为扇出交换机只要有绑定了就都会转发 不需要进行一个匹配
        if(exchangeType == ExchangeType.FANOUT){
            return true;
        }else if (exchangeType == ExchangeType.TOPIC){
            boolean ok = matchKey(binding.getBindingKey(), message.getMessageRoutineKey());
            return ok;
        }else {
            try {
                throw new mqException("交换机类型不存在" + exchangeType);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }
}
